home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 423_01 / accpost / post.c < prev    next >
Text File  |  1990-08-31  |  28KB  |  1,113 lines

  1. /* Plain Vanilla Posting II
  2.  
  3. Copyright 1990 Plain Vanilla Corporation
  4. P.O. Box 4493, San Diego CA 92164
  5. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <setjmp.h>
  10. #include <string.h>
  11. #include <dos.h>
  12. #include <alloc.h>
  13.  
  14. static char id[] = {0x17,0xFD,0x46,0x0F,0x74,0xB3};
  15. static char s1[] = "Changeable journal name (0=no, 1=yes)";
  16. static int changeable_journal_name = 0;
  17. static char sx[] = "";
  18.  
  19. #define MAXIMUM_NAME_OR_FILESPEC_LENGTH 64
  20. #define MAXIMUM_FILESPEC_LENGTH         64
  21. #define MAXIMUM_NAME_LENGTH             40
  22. #define JOURNAL_NAME_LENGTH             12
  23.  
  24. typedef long amount_type;
  25.  
  26. extern amount_type multiply_10(amount_type);
  27. extern amount_type divide_10(amount_type);
  28. extern amount_type sum(amount_type, amount_type);
  29. extern amount_type negative(amount_type);
  30. extern int remainder_10(amount_type);
  31.  
  32. #define AMOUNT_WIDTH  13
  33.  
  34. #define isdebit(x)  ((x)>0)
  35. #define iscredit(x) ((x)<0)
  36. #define iszero(x)   ((x)==0)
  37. #define zero        0L
  38.  
  39. static char *edit_line_number(unsigned n)
  40. {
  41.   static char s[] = {'x','x','x','x',0};
  42.   int i;
  43.   for (i=3; i>=0; i--, n/=10) s[i] = n%10+'0';
  44.   return s;
  45. }  
  46.  
  47. /* case-insensitive strcmp() */
  48.  
  49. static int ci_strcmp(char *s, char *t)
  50. {
  51.   while (*s!=0 && toupper(*s)==toupper(*t)) {s++; t++;}
  52.   return toupper(*s)-toupper(*t);
  53. }
  54.  
  55. static struct
  56. {
  57.   jmp_buf jump_buffer;
  58.   char *message;
  59.   char *name;
  60.   int level;
  61. } err;
  62.  
  63. struct file
  64. {
  65.   int c;
  66.   FILE *fp;
  67.   char *command_line_argument_pointer;
  68.   unsigned line;
  69.   int indented, new_entry;
  70.   char specs[MAXIMUM_FILESPEC_LENGTH+1];
  71. };
  72.  
  73. static struct file source;
  74.  
  75. static FILE *output;
  76. static char output_specs[MAXIMUM_FILESPEC_LENGTH+1];
  77.  
  78. #define error() setjmp(err.jump_buffer)
  79.  
  80. static void error_message(void)
  81. {
  82.   if (source.specs[0]!=0) fputs(source.specs, stdout);
  83.   if (source.line!=0)
  84.   {
  85.     putchar(':');
  86.     fputs(edit_line_number(source.line), stdout);
  87.   }
  88.   putchar(' ');
  89.   fputs(err.message,stdout);
  90.   if (err.name!=NULL)
  91.   {
  92.     fputs(" -- ", stdout);
  93.     fputs(err.name, stdout);
  94.   }
  95.   putchar('\n');
  96.   err.level = 1;
  97. }
  98.  
  99. static void error_exit(void)
  100. {
  101.   error_message();
  102.   exit(err.level);
  103. }
  104.  
  105. static void raise_error_with_name(char *message, char *name)
  106. {
  107.   err.message = message;
  108.   err.name = name;
  109.   longjmp(err.jump_buffer, 1);
  110. }
  111.  
  112. void raise_error(char *message)
  113. {
  114.   raise_error_with_name(message, NULL);
  115. }
  116.  
  117. static void declare_error_with_name(char *message, char *name)
  118. {
  119.   err.message = message;
  120.   err.name = name;
  121.   error_message();
  122. }
  123.  
  124. static void declare_error(char *message)
  125. {
  126.   declare_error_with_name(message, NULL);
  127. }
  128.  
  129. static void open_source_file(char *specs)
  130. {
  131.   if (specs[0]=='[')
  132.   {
  133.     source.command_line_argument_pointer = specs+1;
  134.     specs = "[]";
  135.   }
  136.   else
  137.   {
  138.     if (specs[0]=='+') specs++;
  139.     source.fp = fopen(specs,"r");
  140.     if (source.fp==NULL)
  141.       raise_error_with_name("Can't open source file", specs);
  142.     source.command_line_argument_pointer = NULL;
  143.   }
  144.   strcpy(source.specs, specs);
  145.   source.c = '\n';
  146.   source.line = 0;
  147. }
  148.  
  149. static void read_character(void)
  150. {
  151.   if (source.c!=EOF)
  152.   {
  153.     if (source.c=='\n' && source.line<9999) source.line++;
  154.     if (source.command_line_argument_pointer==NULL)
  155.       source.c = getc(source.fp);
  156.     else
  157.     {
  158.       source.c = *source.command_line_argument_pointer++;
  159.       if (source.c==0) source.c = EOF;
  160.     }
  161.   }
  162. }
  163.  
  164. static void close_source_file(void)
  165. {
  166.   if (source.command_line_argument_pointer==NULL);
  167.     fclose(source.fp);
  168. }
  169.  
  170. static void invalid_amount(void)
  171. {
  172.   raise_error("Invalid dollar amount");
  173. }
  174.  
  175. static void skip_spaces(void)
  176. {
  177.   while (source.c==' ' || source.c=='\t') read_character();
  178. }
  179.  
  180. static void next_line(void)
  181. {
  182.   source.indented = source.new_entry = 0;
  183.   while (1)
  184.   {
  185.     source.indented = 0;
  186.     while (source.c!='\n')
  187.     {
  188.       if (source.c==EOF) {source.new_entry = 1; return;}
  189.       read_character();
  190.     }
  191.     read_character();
  192.     if (source.c==' ' || source.c=='\t') source.indented = 1;
  193.     skip_spaces();
  194.     if (isalpha(source.c)) break;
  195.     if (source.c=='\n' || source.c==EOF) source.new_entry = 1;
  196.     else if (source.c!='*') declare_error("Questionable journal line");
  197.   }
  198. }
  199.  
  200. static amount_type read_amount(void)
  201. {
  202.   int commas = 0;
  203.   int cents = 0;
  204.   int position = 0;
  205.   int nothing = 1;
  206.   amount_type amount;
  207.   amount = zero;
  208.   skip_spaces();
  209.   while (1)
  210.   {
  211.     if (source.c==',')
  212.     {
  213.       if (nothing || cents || commas && position!=4 || !commas && position>3)
  214.         invalid_amount();
  215.       commas = 1;
  216.       position = 0;
  217.       commas = 1;
  218.     }
  219.     else if (source.c=='.')
  220.     {
  221.       if (nothing || cents || commas && position!=4) invalid_amount();
  222.       cents = 1;
  223.       commas = 0;
  224.       position = 0;
  225.     }
  226.     else if (isdigit(source.c))
  227.     {
  228.       nothing = 0;
  229.       if (commas && position==4 || cents && position==3) invalid_amount();
  230.       amount = sum(multiply_10(amount), (amount_type)(source.c-'0'));
  231.     }
  232.     else break;
  233.     read_character();
  234.     position++;
  235.   }
  236.   if (nothing || cents && position!=3 || commas && position!=4)
  237.     invalid_amount();
  238.   if (!cents)
  239.   {
  240.     amount = multiply_10(amount);
  241.     amount = multiply_10(amount);
  242.   }
  243.   return amount;
  244. }
  245.  
  246.  
  247. static unsigned read_number(void)
  248. {
  249.   int no_number = 1;
  250.   unsigned number = 0;
  251.   skip_spaces();
  252.   while (isdigit(source.c))
  253.   {
  254.     if (number>6552) {number = 0xFFFF; break;}
  255.     number = 10*number + source.c - '0';
  256.     no_number = 0;
  257.     read_character();
  258.   }
  259.   if (no_number) number = 0xFFFF;
  260.   return number;
  261. }
  262.  
  263. static int invalid_file_character(int c)
  264. {
  265.   return c<=' ' || c=='"' || c=='/'  || c=='[' || c==']' ||
  266.          c=='|' || c=='<' || c=='>'  || c=='+' || c=='=' ||
  267.          c==';' || c==',';
  268. }
  269.  
  270. static void read_specs(char *specs)
  271. {
  272.   int i = 0;
  273.   skip_spaces();
  274.   if (source.c=='+')
  275.   {
  276.     specs[i++] = '+';
  277.     read_character();
  278.   }
  279.   if (invalid_file_character(source.c))
  280.     raise_error("Invalid or missing file specifications");
  281.   while (!invalid_file_character(source.c))
  282.   {
  283.     if (i<MAXIMUM_FILESPEC_LENGTH) specs[i++] = source.c;
  284.     read_character();
  285.   }
  286.   specs[i] = 0;
  287.   skip_spaces();
  288. }
  289.  
  290. static void read_name(char *name)
  291. {
  292.   int i = 0;
  293.   skip_spaces();
  294.   if (!isalpha(source.c))
  295.     raise_error("Invalid or missing name");
  296.   do
  297.   {
  298.     do
  299.     {
  300.       if (i<MAXIMUM_NAME_LENGTH) name[i++] = source.c;
  301.       read_character();
  302.     } while (isalnum(source.c) || source.c=='/');
  303.     if (i<MAXIMUM_NAME_LENGTH) name[i++] = ' ';
  304.     skip_spaces();
  305.   } while (isalpha(source.c));
  306.   if (name[i-1]==' ') i--;
  307.   name[i] = 0;
  308. }
  309.  
  310. static void *get_memory(int n)
  311. {
  312.   void *g = malloc((unsigned long)n);
  313.   char *t;
  314.   if (g==NULL)
  315.   {
  316.     puts("\nInsufficient memory");
  317.     exit(1);
  318.   }
  319.   for (t=g; n>0; n--) *t++ = 0;
  320.   return g;
  321. }
  322.  
  323. static void open_output_file(char *specs)
  324. {
  325.   if (specs==NULL) output = stdout;
  326.   else
  327.   {
  328.     if (specs[0]=='+') output = fopen(specs+1,"a");
  329.     else output = fopen(specs,"w");
  330.     if (output==NULL) raise_error_with_name("Can't open output file", specs);
  331.     strcpy(output_specs, specs);
  332.   }
  333. }
  334.  
  335. static void close_output_file(void)
  336. {
  337.   if (output!=stdout && output!=NULL) fclose(output);
  338.   output = NULL;
  339. }
  340.  
  341. static void write_character(int c)
  342. {
  343.   if (output==stdout) putchar(c);
  344.   else if (putc(c,output)==EOF)
  345.   {
  346.     close_output_file();
  347.     raise_error_with_name("File write error", output_specs);
  348.   }
  349. }
  350.  
  351. static void write_string(char *s)
  352. {
  353.   while (*s!=0) write_character(*s++);
  354. }
  355.  
  356. static void write_amount(amount_type amount, int trim)
  357. {
  358.   char s[AMOUNT_WIDTH+1];
  359.   register char *t = s+sizeof(s);
  360.   *--t = 0;
  361.   *--t = remainder_10(amount)+'0'; amount = divide_10(amount);
  362.   *--t = remainder_10(amount)+'0'; amount = divide_10(amount);
  363.   *--t = '.';
  364.   do
  365.   {
  366.     if (t==s+7 || t==s+3) *--t = ',';
  367.     *--t = remainder_10(amount)+'0';
  368.     amount = divide_10(amount);
  369.   } while (!iszero